﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using BusinessLayer;

namespace ServiceLayer
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
    public class Repository : IRepository
    {
        public List<CarDTO> ReadAllCars()
        {
            List<CarDTO> result = new List<CarDTO>();
            Reader<Car> reader = Car.Repository.ReadAll();
            while (reader.Read())
            {
                result.Add(new CarDTO(reader.Current));
            }
            reader.Close();
            return result;
        }

        public CarDTO ReadCarById(int id)
        {
            return new CarDTO(Car.Repository.ReadById(id));
        }

        public CarDTO CreateCar()
        {
            return new CarDTO(Car.Repository.Create());
        }

        public void RemoveCar(int id)
        {
            Car.Repository.Remove(id);
        }

        public List<CarDriverDTO> GetCarDrivers(int carId)
        {
            List<CarDriverDTO> result = new List<CarDriverDTO>();
            List<CarDriver> carDrivers = Car.Repository.GetDrivers(carId);
            foreach (CarDriver carDriver in carDrivers)
            {
                result.Add(new CarDriverDTO(carDriver));
            }
            return result;
        }

        public void SetCarDriver(int carId, int driverId, DateTime @from, DateTime to)
        {
            Car.Repository.SetDriver(carId, driverId, from, to);
        }

        public void RemoveCarDriversBefore(int carId, DateTime time)
        {
            Car.Repository.RemoveDriversBefore(carId, time);
        }

        public void SaveCar(CarDTO car)
        {
            Car blCar = Car.Repository.ReadById(car.Id);
            blCar.Name = car.Name;
            blCar.CarNumber = car.CarNumber;
            blCar.Enabled = car.Enabled;
            blCar.Save();
        }

        public CarStateDTO GetCurrentState(int carId)
        {
            return new CarStateDTO(Car.Repository.ReadById(carId).CurrentState());
        }

        public DriverDTO GetCurrentDriver(int carId)
        {
            return new DriverDTO(Car.Repository.ReadById(carId).CurrentDriver());
        }

        public bool IsCarInPark(int carId)
        {
            return Car.Repository.ReadById(carId).IsInPark();
        }

        public List<CarStateDTO> ReadAllCarStates(int carId)
        {
            List<CarStateDTO> result = new List<CarStateDTO>();
            Reader<CarState> reader = CarState.Repository.ReadAll(carId);
            while (reader.Read())
            {
                result.Add(new CarStateDTO(reader.Current));
            }
            reader.Close();
            return result;
        }

        public void RemoveCarStates(int carId, DateTime time)
        {
            CarState.Repository.Remove(carId, time);
        }

        public void RemoveAllCarStates(int carId)
        {
            CarState.Repository.Remove(carId);
        }

        public void RemoveCarStatesOfAllCars(DateTime time)
        {
            CarState.Repository.Remove(time);
        }

        public List<DriverDTO> ReadAllDrivers()
        {
            List<DriverDTO> result = new List<DriverDTO>();
            Reader<Driver> reader = Driver.Repository.ReadAll();
            while (reader.Read())
            {
                result.Add(new DriverDTO(reader.Current));
            }
            reader.Close();
            return result;
        }

        public DriverDTO ReadDriverById(int id)
        {
            return new DriverDTO(Driver.Repository.ReadById(id));
        }

        public DriverDTO CreateDriver()
        {
            return new DriverDTO(Driver.Repository.Create());
        }

        public void RemoveDriver(int id)
        {
            Driver.Repository.Remove(id);
        }

        public void SaveDriver(DriverDTO driver)
        {
            Driver blDriver = Driver.Repository.ReadById(driver.Id);
            blDriver.Name = driver.Name;
            blDriver.Surname = driver.Surname;
            blDriver.PhoneNumber = driver.PhoneNumber;
            blDriver.Email = driver.Email;
            blDriver.Save();
        }

        public List<ParkDTO> ReadAllParks()
        {
            List<ParkDTO> result = new List<ParkDTO>();
            Reader<Park> reader = Park.Repository.ReadAll();
            while (reader.Read())
            {
                result.Add(new ParkDTO(reader.Current));
            }
            reader.Close();
            return result;
        }

        public ParkDTO ReadParkById(int id)
        {
            return new ParkDTO(Park.Repository.ReadById(id));
        }

        public ParkDTO CreatePark()
        {
            return new ParkDTO(Park.Repository.Create());
        }

        public void RemovePark(int id)
        {
            Park.Repository.Remove(id);
        }

        public void SavePark(ParkDTO park)
        {
            Park blPark = Park.Repository.ReadById(park.Id);
            blPark.Name = park.Name;
            blPark.NumberOfSlots = park.NumberOfSlots;
            blPark.NumberOfAvailableSlots = park.NumberOfAvailableSlots;

            List<Point> points = new List<Point>();
            foreach (PointDTO point in park.Location.Points)
            {
                points.Add(new Point(point.X, point.Y));
            }
            blPark.Location = new Polygon(points);
        }

        public List<CarDTO> CarsInPark(int id)
        {
            List<CarDTO> result = new List<CarDTO>();
            List<Car> cars = Park.Repository.ReadById(id).CarsInPark();
            foreach (Car car in cars)
            {
                result.Add(new CarDTO(car));
            }
            return result;
        }

        public List<PrivilegeLevelDTO> ReadAllPrivilegeLevels()
        {
            List<PrivilegeLevelDTO> result = new List<PrivilegeLevelDTO>();
            Reader<PrivilegeLevel> reader = PrivilegeLevel.Repository.ReadAll();
            while (reader.Read())
            {
                result.Add(new PrivilegeLevelDTO(reader.Current));
            }
            reader.Close();
            return result;
        }

        public PrivilegeLevelDTO ReadPrivilegeLevelById(int id)
        {
            return new PrivilegeLevelDTO(PrivilegeLevel.Repository.ReadById(id));
        }

        public PrivilegeLevelDTO CreatePrivilegeLevel()
        {
            return new PrivilegeLevelDTO(PrivilegeLevel.Repository.Create());
        }

        public void RemovePrivilegeLevel(int id)
        {
            PrivilegeLevel.Repository.Remove(id);
        }

        public void SavePrivilegeLevel(PrivilegeLevelDTO privilegeLevel)
        {
            PrivilegeLevel blPrivilegeLevel = PrivilegeLevel.Repository.ReadById(privilegeLevel.Id);
            blPrivilegeLevel.Name = privilegeLevel.Name;
        }

        public List<UserDTO> ReadAllUsers()
        {
            List<UserDTO> result = new List<UserDTO>();
            Reader<User> reader = User.Repository.ReadAll();
            while (reader.Read())
            {
                result.Add(new UserDTO(reader.Current));
            }
            reader.Close();
            return result;
        }

        public UserDTO ReadUserById(int id)
        {
            return new UserDTO(User.Repository.ReadById(id));
        }

        public UserDTO CreateUser()
        {
            return new UserDTO(User.Repository.Create());
        }

        public void RemoveUser(int id)
        {
            User.Repository.Remove(id);
        }

        public void SaveUser(UserDTO user)
        {
            User blUser = User.Repository.ReadById(user.Id);
            blUser.Username = user.Username;
            blUser.Password = user.Password;
            blUser.PrivilegeLevel = PrivilegeLevel.Repository.ReadById(user.PrivilegeLevel.Id);
            blUser.Save();
        }

        public bool ValidateUser(string username, string password)
        {
            return User.Repository.ValidateUser(username, password);
        }
    }
}
